trait Loss {
    fn gradient(y_true: &List<f64>, y_pred: &List<f64>) -> Vec<f64>;
    fn hessian(y_true: &List<f64>, y_pred: &List<f64>) -> Vec<Vec<f64>>;
    fn call(y: &List<f64>, y_pred: &List<f64>) -> f64;
}

struct MSE {}

impl Loss for MSE {
    fn gradient(y_true: &List<f64>, y_pred: &List<f64>) -> Vec<f64> {
        let mut gradient:Vec<f64> = vec![];

        let iter = y_true.iter().zip(y_pred.iter());
        for (y_true_i, y_pred_i) in iter {
            gradient.push(y_true_i - y_pred_i);
        }

        return gradient;
    }

    fn hessian(y_true: &List<f64>, y_pred: &list<f64>) -> Vec<Vec<f64>> {
        let mut hessian: Vec<Vec<f64>> = Vec::new();
    }

    fn call(y_true: &Vec<f64>, y_pred: &Vec<f64>) -> f64 {
        return y_true.iter().zip(y_pred.iter()).map(|(y_true_i, y_pred_i)| (y_true_i - y_pred_i).pow(2) ).sum();
    }
}